﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using Semantics;
using System.Windows.Forms;

namespace GraphBase.Presentation
{
    /// <summary>
    /// 服务于GraphGraphUserControl，用作图的准备与绘画
    /// </summary>
    public class GraphPositionManager : IGraphPositionView
    {
        public Size DisplayArea;
        
        //public GraphBase.GraphDatabase GraphDatabase;
        public IGraph GraphDatabase;
        Extension.VisualGraph VisualGraph;
        GraphGraphUserControl gguc;
        internal GraphPositionManager(IGraph db, Extension.VisualGraph vg,GraphGraphUserControl graphgraphusercontrol,Size size)
        {
            this.GraphDatabase = db;
            this.VisualGraph = vg;
            gguc = graphgraphusercontrol;
            this.DisplayArea = size;
        }

        IList<Node> nodes;//所有节点
        /// <summary>
        /// 节点位置序列
        /// </summary>
        public SortedList<int, NodePos> NodePositions = new SortedList<int, NodePos>();
        // 单一关系边用直线画
        public SortedList<int, EdgePos> EdgeLines = new SortedList<int, EdgePos>();
        // 重复关系的用圆弧画
        public SortedList<int, EdgePos> EdgePoints = new SortedList<int, EdgePos>();

        #region"准备节点与边"
        //准备节点
        /// <summary>
        /// 动态分配每个节点的位置
        /// </summary>
        /// <returns>NodePositions</returns>
        Random r1 = new Random();
        public SortedList<int, NodePos> PrepareDrawingNodesGraph(IList<Node> nodes)
        {
            NodePositions.Clear();
            //this.nodes = this.GraphDatabase.QueryNodes();
            this.VisualGraph.Reload();//其中会通过GetNodesAttributes获得node的Location
            foreach (Node node in nodes)
            {                           
               PrepareNode(node);
            }
            return NodePositions;
        }

        public SortedList<int, NodePos> PrepareNeighborNodes(List<SortedList<int, Node>> neighborNodes)
        {
            NodePositions.Clear();
            this.VisualGraph.Reload();
            foreach (SortedList<int, Node> neighbornodes in neighborNodes)
            {
                foreach (Node node in neighbornodes.Values)
                {
                    PrepareNode(node);
                }
            }
            return NodePositions;
        }

        public NodePos PrepareNode(Node node)
        {
            NodePos np = this.VisualGraph.GetNodePos(node);
            if (np == null)
            {
                object attribute = null;
                if (node.NodeAttributes.TryGetValue(Node.AttributesNames.Location, out attribute))
                {
                    Point location = (Point)attribute;
                    np = new NodePos(node, location);
                }
                else
                {
                    PointF nposp = new PointF(0, 0);
                    nposp.X = r1.Next(20, this.DisplayArea.Width);
                    nposp.Y = r1.Next(20, this.DisplayArea.Height);
                    np = new NodePos(node, (int)nposp.X, (int)nposp.Y);
                }
            }
            else
            {
                if (np.cPoint.X < 0)
                {
                    np.cPoint = new Point(0, np.cPoint.Y);
                }

                if (np.cPoint.Y < 0)
                {
                    np.cPoint = new Point(np.cPoint.X, 0);
                }
            }
            this.NodePositions.Add(node.Id, np);
            np.pNode.Tag = node;
            return np;
        }
        
        // 圆弧的开始位置，中点位置，结束位置，初始点与终点连接直线上的中点，弧上和直线边上显示文字的位置：在圆弧中点位置
        PointF startpt = new PointF(); 
        PointF middlept = new PointF();
        PointF endpt = new PointF();
        PointF ptxt = new PointF();
        float arc_p = 0.2F;//高比
        float arc_d = 0.0F;//middlept与m_line的距离
        IList<Edge> ArcEdges;//=new List<Edge>();//画圆弧时用的边
        //准备直线边
        public SortedList<int, EdgePos> PrepareLineEdges(IList<Edge> lineedges)//圆弧准备边，当为单一关系时
        {
            EdgeLines.Clear();
            foreach (Edge lineedge in lineedges)
            {
                PrepareEdge(lineedge);
            }
            return EdgeLines;
        }

        internal void UpdateLineEdges(IList<Edge> edges)
        {
            foreach (Edge edge in edges)
            {
                EdgePos pos = null;
                if (!this.EdgeLines.TryGetValue(edge.Id, out pos))
                {
                    pos = this.PrepareEdge(edge);
                }
                else
                    this.UpdateEdgePos(edge, pos);
            }
        }
        List<Edge> edgeNeighbors;
        List<Edge> getNeighborEdges(List<SortedList<int, NodePos>> neighbors)
        {
            edgeNeighbors = new List<Edge>();
            NodePosSearchEngine engine = new NodePosSearchEngine(this.GraphDatabase, this);
            List<SortedList<int, List<Edge>>> neighborsEdges = engine.Edges(neighbors);
            foreach (SortedList<int, List<Edge>> level in neighborsEdges)
            {
                foreach (List<Edge> edges in level.Values)
                {
                    foreach (Edge edge in edges)
                    {
                        edgeNeighbors.Add(edge);
                    }
                }
            }
            return edgeNeighbors;
        }
        public SortedList<int, EdgePos> PrepareNeighborEdges(List<Edge> lineedges)
        {
            if (Neighbors.Count > 0)
            {
                this.getNeighborEdges(Neighbors);
                EdgeLines.Clear();
                if (edgeNeighbors.Count > 0)
                {
                    foreach (Edge edge in edgeNeighbors)
                    {
                        PrepareEdge(edge);
                    }
                }
                return EdgeLines;
            }
            else
            {
                EdgeLines.Clear();
                foreach (Edge lineedge in lineedges)
                {
                    PrepareEdge(lineedge);
                }
                return EdgeLines;
            }
        }
        #region 准备边

        /// <summary>
        /// 准备直线边
        /// </summary>
        /// <param name="findedge"></param>
        /// <returns></returns>
        EdgePos PrepareEdge(Edge findedge)
        {
            if(EdgeLines.ContainsKey(findedge.Id))
                throw new Exception(findedge + " already enrolled!");
            EdgePos ep = new EdgePos(findedge);
            UpdateEdgePos(findedge, ep);
            EdgeLines.Add(findedge.Id, ep);
            return ep;
        }

        void UpdateEdgePos(Edge findedge, EdgePos pos)
        {
            NodePos outgo;
            PointF startpoint = new PointF(); PointF endpoint = new PointF();
            if(this.NodePositions.TryGetValue(findedge.Outgoing.Id, out outgo))
            {               
                startpt.X = outgo.cPoint.X + 17;
                startpt.Y = outgo.cPoint.Y + 17;
               // startpoint = outgo .cPoint;  
                startpoint = startpt;
                                
            }           
            if (this.NodePositions.ContainsKey(findedge.Incoming.Id))
            {               
                endpt.X = this.NodePositions[findedge.Incoming.Id].cPoint.X + 17;
                endpt.Y = this.NodePositions[findedge.Incoming.Id].cPoint.Y + 17;
              //  endpoint = this.NodePositions[findedge.Incoming.Id].cPoint;
                endpoint = endpt;
                
            }
            //根据outgo 和Incoming节点的相对位置确定startpt和endpt的位置
            if (startpoint != null && endpoint != null)
            {
                this.CalculatePosition(startpoint, endpoint, ref startpt, ref endpt);
            }
            
            ptxt.X = (endpt.X + startpt.X) / 2;
            ptxt.Y = (endpt.Y + startpt.Y) / 2;
            pos.startPoint = startpt;
            pos.endPoint = endpt;
            pos.Ptext = ptxt;
        }
        /// <summary>
        ///根据startpoint和endpoint的相对位置计算startpt和endpt的值
        /// </summary>
        /// <param name="startpoint"></param>
        /// <param name="endpoint"></param>
        /// <param name="startpt"></param>
        /// <param name="endpt"></param>
        private void CalculatePosition(PointF startpoint, PointF endpoint, ref PointF startpt, ref PointF endpt)
        {
            float  r = 35/2;
            //根据联立方程
            //(x-x1)^2+(y-y1)^2=r^2
            //(y-y1)/(y1-y2)=(x-x1)/(x1-x2);求出通过圆心的直线与圆心（x1,y1)相交的两个交点
            //d1=(y1-y2)^2/(x1-x2)^2,d2=1/d1
            //(x1+sqr(r^2/(1+d1)),y1+sqr(r^2/(1+d2)));(x1-sqr(r^2/(1+d1)),y1-sqr(r^2/(1+d2)))
            //fe
            //根据联立方程
            //(x-x2)^2+(y-y2)^2=r^2
            //(y-y2)/(y2-y1)=(x-x2)/(x2-x1);求出通过圆心的直线与圆心（x2,y2)相交的两个交点
            //(x2+sqr(r^2/(1+d)),y2+sqr(r^2/(1+d2)));(x2-sqr(r^2/(1+d)),y2-sqr(r^2/(1+d2)))

            float d1;
            if (startpoint.X != endpoint.X)
                d1 = (startpoint.Y - endpoint.Y) / (startpoint.X - endpoint.X);
            else
                d1 = 0;
            d1 = d1 * d1;
            float d2;
            if (d1 != 0)
                d2 = 1 / d1;
            else
                d2 = 0;
            double x13, y13, dx, dy, x14, y14;
            dx=Math .Sqrt((r*r)/(1+d1));dy=Math .Sqrt ((r*r)/(1+d2));
            x13 = startpoint.X + dx; y13 = startpoint.Y + dy;
            x14 = startpoint.X - dx; y14 = startpoint.Y - dy;

            double x23, y23, x24, y24;
            x23 = endpoint.X + dx; y23 = endpoint.Y + dy;
            x24 = endpoint.X - dx; y24 = endpoint.Y - dy;

            startpt.X =(float) x13;
            startpt.Y =(float) y13;

            endpt.X = (float)x23;
            endpt.Y = (float)y23;
            if (startpoint.X < endpoint.X)
            {
                if (startpoint.Y > endpoint.Y)
                {
                    startpt.X = (float)x13;
                    startpt.Y = (float)y14;

                    endpt.X = (float)x24;
                    endpt.Y = (float)y23;
                }
                else
                {
                    startpt.X = (float)x13;
                    startpt.Y = (float)y13;

                    endpt.X = (float)x24;
                    endpt.Y = (float)y24;
                }             
              
            }
            if (startpoint.X > endpoint.X)
            {
                if (startpoint.Y > endpoint.Y)
                {
                    startpt.X = (float)x14;
                    startpt.Y = (float)y14;

                    endpt.X = (float)x23;
                    endpt.Y = (float)y23;
                }
                else
                {
                    startpt.X = (float)x14;
                    startpt.Y = (float)y13;

                    endpt.X = (float)x23;
                    endpt.Y = (float)y24;
                }                
            }
            if (startpoint.X == endpoint.X)
            {
                if (startpoint.Y > endpoint.Y)
                {
                    startpt.X = startpoint.X;
                    startpt.Y = startpoint.Y + r;
                    endpt.X = endpoint .X;
                    endpt.Y = endpoint.Y - r;

                }
                else
                {
                    startpt.X = startpoint.X;
                    startpt.Y = startpoint.Y - r;
                    endpt.X = endpoint.X;
                    endpt.Y = endpoint.Y + r;
                   
                }

            }
            //if(startpoint .X <endpoint.X)
            //{
            //    startpt.X = startpoint.X + r;
            //    startpt.Y = startpoint.Y + r/2;
            //    endpt.X = endpoint.X;
            //    endpt.Y = endpoint.Y+r/2;
            //}
            //if (startpoint.X > endpoint.X)
            //{
            //    startpt.X = startpoint.X;
            //    startpt.Y = startpoint.Y+r/2;
            //    endpt.X = endpoint.X + r;
            //    endpt.Y = endpoint.Y + r/2;
            //}
            //if (startpoint.X == endpoint.X)
            //{
            //    if (startpoint.Y > endpoint.Y)
            //    {
            //        startpt.X = startpoint.X + r/2;
            //        startpt.Y = startpoint.Y;
            //        endpt.X = endpoint.X+r/2;
            //        endpt.Y = endpoint.Y + r;
            //    }
            //    else
            //    {
            //        startpt.X = startpoint.X + r/2;
            //        startpt.Y = startpoint.Y + r;
            //        endpt.X = endpoint.X+r/2;
            //        endpt.Y = endpoint.Y;
            //    }
                
            //}

        }
        #endregion
        //准备圆弧边
        public SortedList<int, EdgePos> PrepareArcEdges()//圆弧准备边，其余多个关系边
        {
            EdgePoints.Clear();
            //初始角度和扫过的角度
            float startang = 0;
            float sweepsng = 0;
            //矩形左上角坐标
            float rectx = 0;
            float recty = 0;
            //矩形的宽，高
            int width = 0;
            PointF Point_O = new PointF();//圆心 
            float arc_r = 0;//圆的半径
            this.nodes = this.GraphDatabase.GetAllNodes();
            foreach (Node node in nodes)
            {
                if (this.nodes.Count > 1000)
                    throw new Exception("Exceed maxim number!");
                this.ArcEdges = this.GraphDatabase.GetEdges(node);
                if (this.ArcEdges.Count > 0)
                {
                    foreach (Edge findedge in ArcEdges)
                    {
                        if (EdgePoints.ContainsKey(findedge.Id))
                            continue;
                        if(this.EdgeLines.ContainsKey(findedge.Id))
                            continue;
                        PointF startpoint = new PointF(), endpoint = new PointF();
                        if (this.NodePositions.ContainsKey(findedge.Outgoing.Id))
                        {
                            startpt.X = this.NodePositions[findedge.Outgoing.Id].cPoint.X + 17;
                            startpt.Y = this.NodePositions[findedge.Outgoing.Id].cPoint.Y + 17;
                            startpoint = this.NodePositions[findedge.Outgoing.Id].cPoint;
                        }
                        if (this.NodePositions.ContainsKey(findedge.Incoming.Id))
                        {
                            endpt.X = this.NodePositions[findedge.Incoming.Id].cPoint.X + 17;
                            endpt.Y = this.NodePositions[findedge.Incoming.Id].cPoint.Y + 17;
                            endpoint = this.NodePositions[findedge.Incoming.Id].cPoint;
                        }
                        //根据outgo 和Incoming节点的相对位置确定startpt和endpt的位置
                        if (startpoint != null && endpoint != null)
                        {
                            this.CalculatePosition(startpoint, endpoint, ref startpt, ref endpt);
                        }
                        arc_d = arc_p * Geometry.getDirection(startpt, endpt);//弧上中点与初始点和终点的中点的距离
                        middlept = Geometry.getArcMiddlePoint(startpt, endpt, arc_d);//算出弧上中点
                        Point_O = Geometry.getPoint_O(startpt, endpt, middlept, arc_d);//算出圆心
                        arc_r = Geometry.getDirection(startpt, Point_O);//算出半径
                        startang = Geometry.Start_Angle(startpt, endpt, Point_O);//算出初始角
                        sweepsng = Geometry.AngleCentral(startpt, endpt, arc_d);//扫过的角度即为圆心角（劣弧）
                        ptxt = middlept;
                        //矩形左上角坐标
                        rectx = Point_O.X - arc_r;
                        recty = Point_O.Y - arc_r;
                        //矩形宽，高
                        width = (int)(2 * arc_r);
                        //确定矩形
                        Rectangle recta = new Rectangle((int)rectx, (int)recty, width, width);
                        EdgePos ep = new EdgePos(findedge, recta, (float)startang, (float)sweepsng, ptxt, startpt, endpt, Point_O, arc_d);
                        EdgePoints.Add(findedge.Id, ep);
                        //string findincoming = findedge.Incoming.Label;
                        Edge[] searchEdge = ArcEdges.ToArray();
                        for (int i = 0; i < ArcEdges.Count; i++)
                        {
                            if ((findedge.Outgoing.Label == searchEdge[i].Outgoing.Label) && (findedge.Incoming.Label == searchEdge[i].Incoming.Label) && (findedge.FristLeaf.Class.Label != searchEdge[i].FristLeaf.Class.Label))
                            {
                                arc_p += arc_p;
                            }
                            else
                                arc_p = 0.2F;
                        }
                    }
                }
            }
            return EdgePoints;
        }

        public void ShowNodeNeighbor(Graph resultgraph, List<SortedList<int, Node>> neighborNodes)
        {
            this.EdgePoints.Clear();
            this.EdgeLines.Clear();
            this.NodePositions.Clear();
            NodePosSearchEngine engine = new NodePosSearchEngine(this.GraphDatabase, this);
            this.Neighbors = engine.PrepareNeighbor(neighborNodes);

            SortedList<int, Edge> edgeshash = resultgraph.edgesHash;
            foreach (Edge edge in edgeshash.Values)
            {
                PrepareEdge(edge);
            }

            /*System.Collections.IEnumerator edgeenumerator = resultgraph.edgesHash.GetEnumerator();
            while (edgeenumerator.MoveNext())
            {
                Edge e = (Edge)((System.Collections.DictionaryEntry)edgeenumerator.Current).Label;
                PrepareEdge(e);
            }*/
        }

        #endregion
        
        #region"画节点与边"
        public NodePos SelectedNodePos;
        public EdgePos SelectedLineEdge;
        public EdgePos SelectedArcEdge;

        public void DrawGraphView(Graphics g, SearchEngine.EnumSearchManner searchmanner)
        {
            this.DrawNodes(g, searchmanner);
            this.DrawEdges(g,searchmanner);
        }

        //画新建节点
        public void DrawNode(Graphics g, NodePos node)
        {
            PointF text = new PointF();//节点标记
            Pen pnline = new Pen(Color.Black, 2);//定义line画笔为黑色，宽为2
            int x = node.cPoint.X;
            int y = node.cPoint.Y;
            try
            {
                if (node != null)
                {
                    g.DrawEllipse(new Pen(Color.DarkBlue, 2), x, y, 35, 35);
                    text.X = x + 2;
                    text.Y = y + 10;
                    g.DrawString(node.pNode.Label, new Font("Arial", 9), new SolidBrush(Color.Black), text);
                }
                else
                    return ;
            }
            catch (Exception exp)
            {
                g.DrawString(exp.ToString(), new Font(FontFamily.GenericSansSerif, 10.0f), new SolidBrush(Color.DarkBlue), 10, 10);
            }
            //g.Dispose();
        }
 
        //画节点
        /// <summary>
        /// 先画节点
        /// </summary>
        /// <param name="g"></param>
        /// <param name="manner">是否根据跳数来显示节点</param>
        public void DrawNodes(Graphics g, SearchEngine.EnumSearchManner manner)
        {
            DrawAllNodes(g);
            switch (manner)
            {
                case SearchEngine.EnumSearchManner.ByNeightbor:
                    //DrawAllNeighbor(g,gguc.HopDistance);
                    if (SelectedNodePos != null)
                        DrawNeighbor(g, this.SelectedNodePos, gguc.HopDistance);
                    break;
                case SearchEngine.EnumSearchManner.All:
                default:
                    DrawSelected(g);
                    break;
            }
        }
        //case SearchEngine.EnumSearchManner.ByNeightbor:
        /// <summary>
        /// 当有选中的节点时
        /// </summary>
        /// <param name="g"></param>
        /// <param name="origin">被选中的节点</param>
        void DrawNeighbor(Graphics g, NodePos origin, int distance)
        {
            System.Diagnostics.Trace.WriteLine("DrawNeighbor");
            try
            {
                this.Search(distance, origin);
                for (int j = 0; j < this.Neighbors.Count; j++)
                {
                    SortedList<int, NodePos> level = this.Neighbors[j];
                    foreach (NodePos npos in level.Values)
                    {
                        npos.DrawColorNodes(g, npos.pNode.Label, npos.cPoint, j);
                        //选中直线
                        if (SelectedLineEdge != null)
                        {
                            if (SelectedNodePos != null)
                            {
                                if (npos.pNode.Id == SelectedNodePos.pNode.Id)//选中节点显示黄色
                                    npos.DrawColorNodes(g, SelectedNodePos.pNode.Label, SelectedNodePos.cPoint, 0);
                            }
                            else
                            {
                                if ((SelectedLineEdge.pedge.Incoming.Label == npos.pNode.Label) || (SelectedLineEdge.pedge.Outgoing.Label == npos.pNode.Label))
                                    npos.DrawColorNodes(g, npos.pNode.Label, npos.cPoint, 0);//黄色
                            }
                        }
                        //选中圆弧
                        if (SelectedArcEdge != null)
                        {
                            if (SelectedNodePos != null)
                            {
                                if (npos.pNode.Id == SelectedNodePos.pNode.Id)//选中节点显示黄色
                                    npos.DrawColorNodes(g, SelectedNodePos.pNode.Label, SelectedNodePos.cPoint, 0);
                            }
                            else
                            {
                                if ((SelectedArcEdge.pedge.Outgoing.Label == npos.pNode.Label) || (SelectedArcEdge.pedge.Incoming.Label == npos.pNode.Label))
                                    npos.DrawColorNodes(g, npos.pNode.Label, npos.cPoint, 0);//黄色
                            }
                        }
                        //选中多个节点
                        if (this.gguc.GetSelectedMultipleNodes() != null)
                        {
                            foreach (NodePos np in this.gguc.GetSelectedMultipleNodes())
                            {
                                npos.DrawColorNodes(g, np.pNode.Label, np.cPoint, 0);//黄色
                            }
                        }
                    }
                }
            }
            catch (Exception exp)
            {
                g.DrawString(exp.ToString(), new Font(FontFamily.GenericSansSerif, 10.0f), new SolidBrush(Color.DarkBlue), 10, 10);
            }
        }
        /// <summary>
        /// 当没有节点选中时
        /// </summary>
        /// <param name="g"></param>
        void DrawAllNeighbor(Graphics g)
        {
            try
            {
                foreach (SortedList<int, NodePos> level in Neighbors)
                {
                    foreach (NodePos npos in level.Values)
                    {
                        //默认节点为暗蓝色
                        npos.DrawColorNodes(g, npos.pNode.Label, npos.cPoint, -1);    
                    }
                }
            }
            catch (Exception exp)
            {
                
                g.DrawString(exp.ToString(), new Font(FontFamily.GenericSansSerif, 10.0f), new SolidBrush(Color.DarkBlue), 10, 10);
            }
        }
        //case SearchEngine.EnumSearchManner.All:
        /// <summary>
        /// 画选中的节点或边
        /// </summary>
        /// <param name="g"></param>
        void DrawSelected(Graphics g)
        {
            foreach (NodePos npos in this.NodePositions.Values)
            {
                try
                {
                    //选中节点不为空
                    if (this.SelectedNodePos != null)
                    {
                        if (npos.pNode.Id == SelectedNodePos.pNode.Id)//选中节点显示黄色
                        {
                            npos.DrawColorNodes(g, SelectedNodePos.pNode.Label, SelectedNodePos.cPoint, 0);
                            npos.DrawSelectedRectangle(g);
                        }
                    }
                    //选中直线
                    if (SelectedLineEdge != null)
                    {
                        if (SelectedNodePos != null)
                        {
                            if (npos.pNode.Id == SelectedNodePos.pNode.Id)//选中节点显示黄色
                                npos.DrawColorNodes(g, SelectedNodePos.pNode.Label, SelectedNodePos.cPoint, 0);
                        }
                        else
                        {
                            if ((SelectedLineEdge.pedge.Incoming.Label == npos.pNode.Label) || (SelectedLineEdge.pedge.Outgoing.Label == npos.pNode.Label))
                                npos.DrawColorNodes(g, npos.pNode.Label, npos.cPoint, 0);//黄色
                        }
                    }
                    //选中圆弧
                    if (SelectedArcEdge != null)
                    {
                        if (SelectedNodePos != null)
                        {
                            if (npos.pNode.Id == SelectedNodePos.pNode.Id)//选中节点显示黄色
                                npos.DrawColorNodes(g, SelectedNodePos.pNode.Label, SelectedNodePos.cPoint, 0);
                        }
                        else
                        {
                            if ((SelectedArcEdge.pedge.Outgoing.Label == npos.pNode.Label) || (SelectedArcEdge.pedge.Incoming.Label == npos.pNode.Label))
                                npos.DrawColorNodes(g, npos.pNode.Label, npos.cPoint, 0);//黄色
                        }
                    }
                    //选中多个节点
                    if (this.gguc.GetSelectedMultipleNodes().Count>0)
                    {
                        foreach (NodePos np in this.gguc.GetSelectedMultipleNodes())
                        {
                            npos.DrawColorNodes(g, np.pNode.Label, np.cPoint, 0);//黄色
                        }
                    }
                    else
                        npos.DrawColorNodes(g, npos.pNode.Label, npos.cPoint, -1);
                }
                catch (Exception exp)
                {
                    g.DrawString(exp.ToString(), new Font(FontFamily.GenericSansSerif, 10.0f), new SolidBrush(Color.DarkBlue), 10, 10);
                }
            }
        }
        /// <summary>
        /// 画所有的节点
        /// </summary>
        /// <param name="g"></param>
        void DrawAllNodes(Graphics g)
        {
            System.Diagnostics.Trace.WriteLine("DrawAllNodes");
            foreach (NodePos npos in this.NodePositions.Values)
            {
                try
                {
                    //默认节点为暗蓝色
                    npos.DrawColorNodes(g, npos.pNode.Label, npos.cPoint, -1);                   
                }
                catch (Exception exp)
                {
                    g.DrawString(exp.ToString(), new Font(FontFamily.GenericSansSerif, 10.0f), new SolidBrush(Color.DarkBlue), 10, 10);
                }
            }
        }

        //画边
        /// <summary>
        /// 再画边
        /// </summary>
        /// <param name="g"></param>
        /// <param name="manner"></param>
        public void DrawEdges(Graphics g, SearchEngine.EnumSearchManner manner)
        {
            DrawAllEdges(g);
            switch (manner)
            {
                case SearchEngine.EnumSearchManner.ByNeightbor:
                    DrawAllNeighborEdges(g, Neighbors);
                    if (SelectedNodePos != null)
                        DrawNeighborEdges(g, Neighbors);
                    break;
                case SearchEngine.EnumSearchManner.All:
                default:
                    
                    DrawSelectedEdges(g);
                    break;
            }
        }
        //case SearchEngine.EnumSearchManner.All:
        void DrawAllEdges(Graphics g)
        {
            //默认边为黑色
            try
            {
                //画直线
                foreach (EdgePos epline in this.EdgeLines.Values)
                {
                    epline.DrawColorLineEdges(g, epline, -1);
                }
                //画弧线
                foreach (EdgePos edgepot in this.EdgePoints.Values)
                {
                    edgepot.DrawColorArcEdges(g, edgepot, -1);
                }
            }
            catch (Exception exp)
            {
                g.DrawString(exp.ToString(), new Font(FontFamily.GenericSansSerif, 10.0f), new SolidBrush(Color.DarkBlue), 10, 10);
            }
        }
        void DrawSelectedEdges(Graphics g)
        {
            try
            {
                //选中直线
                if (SelectedLineEdge != null)
                {
                    SelectedLineEdge.DrawColorLineEdges(g, SelectedLineEdge, 0);
                }
                //选中圆弧
                if (SelectedArcEdge != null)
                {
                    SelectedArcEdge.DrawColorArcEdges(g,SelectedArcEdge,0);
                }
            }
            catch (Exception exp)
            {
                g.DrawString(exp.ToString(), new Font(FontFamily.GenericSansSerif, 10.0f), new SolidBrush(Color.DarkBlue), 10, 10);
            }
        }
        //case SearchEngine.EnumSearchManner.ByNeightbor:
        
        void DrawAllNeighborEdges(Graphics g, List<SortedList<int, NodePos>> neighbors)
        {
            NodePosSearchEngine engine = new NodePosSearchEngine(this.GraphDatabase,this);
            List<SortedList<int, List<Edge>>> neighborsEdges=engine.Edges(neighbors);
            try
            {
                foreach (SortedList<int, List<Edge>> level in neighborsEdges)
                {
                    foreach (List<Edge> edges in level.Values)
                    {
                        foreach (Edge edge in edges)
                        {
                            if (EdgeLines.Count > 0)
                            {
                                foreach (EdgePos edgept in EdgeLines.Values)
                                {
                                    if (edgept.pedge == edge)
                                    {
                                        edgept.DrawColorLineEdges(g, edgept,-1);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception exp)
            {  
                g.DrawString(exp.ToString(), new Font(FontFamily.GenericSansSerif, 10.0f), new SolidBrush(Color.DarkBlue), 10, 10);
            }  
        }
        void DrawNeighborEdges(Graphics g, List<SortedList<int, NodePos>> neighbors)
        {
            NodePosSearchEngine engine = new NodePosSearchEngine(this.GraphDatabase,this);
            List<SortedList<int, List<Edge>>> neighborsEdges=engine.Edges(neighbors);
            try
            {
                for (int j = 0; j < neighborsEdges.Count ; j++)
                {
                    SortedList<int, List<Edge>> level = neighborsEdges[j];
                    foreach (List<Edge> edges in level.Values)
                    {
                        foreach (Edge edge in edges)
                        {
                            if (EdgeLines.Count > 0)
                            {
                                foreach (EdgePos edgept in EdgeLines.Values)
                                {
                                    if (edgept.pedge == edge)
                                    {
                                        edgept.DrawColorLineEdges(g, edgept, j + 1);
                                        break;
                                    }
                                }
                            }
                            //EdgePt edgept=this.PrepareEdge(edge);
                        }
                    }
                }    
            }
            catch (Exception exp)
            {
                g.DrawString(exp.ToString(), new Font(FontFamily.GenericSansSerif, 10.0f), new SolidBrush(Color.DarkBlue), 10, 10);
            }
        }
        //public void DrawArcEdges(Graphics g)//画圆弧边
        //{
        //    if (SelectedLineEdge != null)//选中直线
        //    {
        //        try
        //        {
        //            foreach (EdgePt epline in this.EdgeLines.Values)//先画直线
        //            {
        //                if (epline.pedge == SelectedLineEdge.pedge)
        //                {
        //                    //选中直线为蓝色
        //                    epline.DrawColorLineEdges(g, epline, 0);
        //                }
        //                else
        //                {
        //                    //默认为黑色
        //                    epline.DrawColorLineEdges(g, epline, -1);
        //                }
        //            }
        //            foreach (EdgePt edgepot in this.EdgePoints.Values)//再画弧
        //            {
        //                //g.DrawRectangle(new Pen(Color.Blue, 1.0F), edgepot.rectangle);
        //                g.DrawArc(pnline, edgepot.rectangle, edgepot.startAngle, edgepot.sweepAngle);
        //                g.DrawString(edgepot.pedge.FristLeaf.Class.Label, new Font("Arial", 9), new SolidBrush(Color.Black), edgepot.PArctext);
        //            }
        //        }
        //        catch (Exception exp)
        //        {
        //            g.DrawString(exp.ToString(), new Font(FontFamily.GenericSansSerif, 10.0f), new SolidBrush(Color.DarkBlue), 10, 10);
        //        }
        //    }
        //    if (SelectedArcEdge != null)//选中圆弧
        //    {
        //        try
        //        {
        //            foreach (EdgePt epline in this.EdgeLines.Values)//先画直线
        //            {
        //                g.DrawLine(pnline, epline.startPoint, epline.endPoint);
        //                g.DrawString(epline.pedge.FristLeaf.Class.Label, new Font("Arial", 9), new SolidBrush(Color.Black), epline.Ptext);
        //            }
        //            foreach (EdgePt edgepot in this.EdgePoints.Values)//再画弧
        //            {
        //                if (edgepot.pedge == SelectedArcEdge.pedge)
        //                {
        //                    //g.DrawRectangle(new Pen(Color.Blue, 1.0F), edgepot.rectangle);
        //                    g.DrawArc(new Pen(Color.Blue), edgepot.rectangle, edgepot.startAngle, edgepot.sweepAngle);
        //                    g.DrawString(edgepot.pedge.FristLeaf.Class.Label, new Font("Arial", 9), new SolidBrush(Color.Blue), edgepot.PArctext);
        //                }
        //                else
        //                {
        //                    g.DrawArc(pnline, edgepot.rectangle, edgepot.startAngle, edgepot.sweepAngle);
        //                    g.DrawString(edgepot.pedge.FristLeaf.Class.Label, new Font("Arial", 9), new SolidBrush(Color.Black), edgepot.PArctext);
        //                }
        //            }
        //        }
        //        catch (Exception exp)
        //        {
        //            g.DrawString(exp.ToString(), new Font(FontFamily.GenericSansSerif, 10.0f), new SolidBrush(Color.DarkBlue), 10, 10);
        //        }
        //    }
        //    if((this.SelectedNodePos==null&&SelectedLineEdge==null&&SelectedArcEdge==null)||(SelectedNodePos!=null))
        //    {
        //        try
        //        {
        //            foreach (EdgePt epline in this.EdgeLines.Values)//先画直线 
        //            {
        //                g.DrawLine(pnline, epline.startPoint, epline.endPoint);
        //                g.DrawString(epline.pedge.FristLeaf.Class.Label, new Font("Arial", 9), new SolidBrush(Color.Black), epline.Ptext);
        //            }
        //            foreach (EdgePt edgepot in this.EdgePoints.Values)//再画弧
        //            {
        //                //g.DrawRectangle(new Pen(Color.Blue, 1.0F), edgepot.rectangle);
        //                g.DrawArc(pnline, edgepot.rectangle, edgepot.startAngle, edgepot.sweepAngle);
        //                g.DrawString(edgepot.pedge.FristLeaf.Class.Label, new Font("Arial", 9), new SolidBrush(Color.Black), edgepot.PArctext);
        //            }
        //        }
        //        catch (Exception exp)
        //        {
        //            g.DrawString(exp.ToString(), new Font(FontFamily.GenericSansSerif, 10.0f), new SolidBrush(Color.DarkBlue), 10, 10);
        //        }
        //    }
                
        //}
        #endregion

        #region"相应跳数的节点"
        
        /// <summary>
        /// 对应层的节点集
        /// 每个List的成员对应一层的邻接边
        /// Key:节点ID
        /// Value:节点
        /// </summary>
        List<SortedList<int, NodePos>> Neighbors = new List<SortedList<int, NodePos>>();
        public void Search(int distance, NodePos origin)
        {
            NodePosSearchEngine engine = new NodePosSearchEngine(this.GraphDatabase, this);
            this.Neighbors = engine.Search(distance, origin);
            if (Neighbors.Count == 0)
            {
                this.gguc.Refresh();
            }
        }

        #endregion
    }
}
